/*  
    Copyright 2010 Mike Eheler <mike.eheler@gmail.com>

    This file is part of Four Falling Blocks Puzzle Game.

    Four Falling Blocks Puzzle Game is free software: you can
	redistribute it and/or modify it under the terms of the GNU General
	Public License as published by the Free Software Foundation, either
	version 3 of the License, or (at your option) any later version.

    Four Falling Blocks Puzzle Game is distributed in the hope that it
	will be useful, but WITHOUT ANY WARRANTY; without even the implied
	warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
	See the GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Four Falling Blocks Puzzle Game.
	
	If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

#include <vector>

#include "types.h"
#include "board.h"
#include "pieces.h"

class Game
{
public:
	static Game * instance();

	void reset();
	void resetPosition();

	void newGame( bool hellMode = false );
	void endGame();

	void loadHighScores();
	void saveHighScores() const;

	void rotateLeft();
	void rotateRight();
	
	void drop();
	void advance();

	void moveLeft();
	void moveRight();

	int8_t positionX() const;
	int8_t positionY() const;
	void setPosition( int8_t x, int8_t y );

	bool   gameOver() const;
	bool   levelChanged() const;

	uint32_t level() const;
	uint32_t lines() const;
	uint32_t score() const;
	uint32_t pieceCount( uint8_t type ) const;

	HighScore highScore( uint8_t pos = 0 ) const;
	void setHighScore( uint8_t pos, HighScore const & score );

	Piece       * newPiece( uint8_t type );
	Piece       * randomPiece();
	Piece       * currentPiece() const;
	Piece const * nextPiece() const;
	Board       * board();

protected:
	Game();
	virtual ~Game();

	uint32_t mLevel;
	uint32_t mLines;
	uint32_t mScore;
	uint32_t mPieceCounts[7];

	std::vector<HighScore> mHighScores;

	Board mBoard;

	Piece * mCurrentPiece;
	Piece * mNextPiece;

	bool  mHellMode;
	bool  mGameOver;
	bool  mLevelChanged;
	int8_t mPosX;
	int8_t mPosY;
};

// INLINE //
inline Game * Game::instance()
{
	static Game game;
	return &game;
}

inline int8_t Game::positionX() const
{
	return mPosX;
}

inline int8_t Game::positionY() const
{
	return mPosY;
}

inline void Game::setPosition( int8_t x, int8_t y )
{
	mPosX = x;
	mPosY = y;
}

inline Board * Game::board()
{
	return &mBoard;
}

inline Piece * Game::currentPiece() const
{
	return mCurrentPiece;
}

inline Piece const * Game::nextPiece() const
{
	return mNextPiece;
}

inline bool Game::gameOver() const
{
	return mGameOver;
}

inline bool Game::levelChanged() const
{
	return mLevelChanged;
}

inline uint32_t Game::level() const
{
	return mLevel;
}

inline uint32_t Game::lines() const
{
	return mLines;
}

inline uint32_t Game::score() const
{
	return mScore;
}

inline HighScore Game::highScore( uint8_t pos ) const
{
	if( pos < mHighScores.size() ) return mHighScores[pos];
	return HighScore();
}

inline uint32_t Game::pieceCount( uint8_t type ) const
{
	if( type < 8 )
		return mPieceCounts[type];
	
	return 0;
}
